home *** CD-ROM | disk | FTP | other *** search
- /*
- * © Copyright Jeff Francis 1990
- * All rights reserved
- *
- * $Id$
- *
- * Description - CProjectile is an example CAfterDark subclass.
- * CProjectile animates a projectile across the screen. Calculations
- * are made so that the projectile doesn't fly off the screen. The
- * animation isn't all that great but it makes for a reasonable example.
- */
-
- #include "CProjectile.h"
-
- #define kMAXVELOCITY 500
- #define SynchVBL() synchFlag = ¶ms->monitors->monitorList[0].synchFlag; \
- *synchFlag = false; \
- while (!*synchFlag);
-
- /*
- * Initialize seeds the random number generator, gets the value of
- * gravity from the gravity slider and then generates a set of initial
- * conditions.
- */
- OSErr CProjectile::Initialize(RgnHandle blankRgn, GMParamBlockPtr params)
- {
- GetDateTime(&randSeed);
-
- fG = params->controlValues[kGRAVITY_CTRL] + 0.00000001;
- fBallSize = params->controlValues[kBALLSIZE_CTRL];
- this->InitialConditions(params);
-
- return noErr;
- }
-
-
- /*
- * Draw performs animation by erasing the old projectile and then
- * drawing a new projectile at a new position. The new position
- * may be off the screen. If it is, a new set of initial conditions
- * are generated. If not, "time" is incremented.
- */
- OSErr CProjectile::DrawFrame(RgnHandle blankRgn, GMParamBlockPtr params)
- {
- register Boolean *synchFlag;
- Rect aRect1, aRect2;
- float oldX, oldY;
- int ballSize;
-
- /*
- * Get new ball size
- */
- ballSize = params->controlValues[kBALLSIZE_CTRL];
-
- /*
- * Calculate new particle position
- */
- oldX = fX;
- oldY = fY;
- fY = fYo + fG*fT*fT/2 - fVyo*fT;
- fX = fVxo*fT + fXo;
-
- /*
- * If the projectile is off the screen then generate a new set
- * of initial conditions otherwise draw the projectile at the
- * new position.
- */
- if (fY > params->monitors->monitorList[0].bounds.bottom) {
- /*
- * We've fallen off the screen.
- */
- SetRect(&aRect1, (int)oldX-fBallSize, (int)oldY-fBallSize,
- (int)oldX+fBallSize, (int)oldY+fBallSize);
- FillOval(&aRect1, params->qdGlobalsCopy->qdBlack);
-
- this->InitialConditions(params);
- } else {
- fT += params->controlValues[kSPEED_CTRL] / 100.0;
-
- SetRect(&aRect1, (int)oldX-fBallSize, (int)oldY-fBallSize,
- (int)oldX+fBallSize, (int)oldY+fBallSize);
- SetRect(&aRect2, (int)fX-ballSize, (int)fY-ballSize,
- (int)fX+ballSize, (int)fY+ballSize);
-
- SynchVBL();
- FillOval(&aRect1, params->qdGlobalsCopy->qdBlack);
- FillOval(&aRect2, params->qdGlobalsCopy->qdWhite);
- }
-
- /*
- * Save new ball size.
- */
- fBallSize = ballSize;
-
- return noErr;
- }
-
-
- /*
- * InitialConditions generates a set of random initial conditions
- * such that the projectile will not fly beyond the top of the monitor
- * nor will it go beyond the sides of the monitor during its flight.
- */
- void CProjectile::InitialConditions(GMParamBlockPtr params)
- {
- float maxX, maxY;
- int monitorX, monitorY, randomValue;
- Str255 aString;
-
- monitorX = params->monitors->monitorList[0].bounds.right;
- monitorY = params->monitors->monitorList[0].bounds.bottom;
-
- fT = fX = fY = 0.0;
-
- do {
- randomValue = Random();
- randomValue = ABS(randomValue);
- fXo = randomValue % monitorX;
- fYo = monitorY;
-
- fVxo = Random() % kMAXVELOCITY /
- (params->controlValues[kRATIO_CTRL] + 1);
- randomValue = Random();
- randomValue = ABS(randomValue);
- fVyo = randomValue % kMAXVELOCITY;
-
- maxX = 2*fVyo*fVxo/fG + fXo;
- maxY = fVyo*fVyo/2/fG - fYo;
- } while (maxY > 0 || maxX < 0 || maxX > monitorX);
- }